home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- char ident[] = "@(#)IVcalc Version 1.0";
- /*----------------------------------------------------------------
- *
- * ivcalc - 3D calculator built with the Inventor graphics toolkit
- *
- *
- * 03/93 John Magdziarz, Silicon Graphics, Inc.
- *
- *----------------------------------------------------------------*/
-
- #include <ctype.h>
- #include <iostream.h>
- #include <X11/StringDefs.h>
-
- #include <sys/types.h>
- #include <sys/prctl.h>
- #include <sys/schedctl.h>
- #include <audio.h>
- #include <audiofile.h>
-
- #include <Inventor/Xt/SoXt.h>
- #include <Inventor/Xt/SoXtRenderArea.h>
- #include <Inventor/Xt/SoXtComponent.h>
- #include <Inventor/SoDB.h>
- #include <Inventor/SbLinear.h>
- #include <Inventor/SoInput.h>
- #include <Inventor/SoOutput.h>
- #include <Inventor/nodes/SoEventCallback.h>
- #include <Inventor/nodes/SoSelection.h>
- #include <Inventor/sensors/SoSensor.h>
- #include <Inventor/details/SoDetail.h>
- #include <Inventor/events/SoMouseButtonEvent.h>
- #include <Inventor/events/SoEvent.h>
- #include <Inventor/events/SoKeyboardEvent.h>
- #include <Inventor/actions/SoSearchAction.h>
- #include <Inventor/actions/SoGetMatrixAction.h>
- #include <Inventor/actions/SoGetBoundingBoxAction.h>
- #include <Inventor/actions/SoWriteAction.h>
- #include <Inventor/actions/SoRayPickAction.h>
- #include <Inventor/nodes/SoLabel.h>
- #include <Inventor/nodes/SoGroup.h>
- #include <Inventor/nodes/SoFont.h>
- #include <Inventor/nodes/SoText3.h>
- #include <Inventor/nodes/SoTransform.h>
- #include <Inventor/nodes/SoTranslation.h>
- #include <Inventor/nodes/SoRotationXYZ.h>
- #include <Inventor/nodes/SoScale.h>
- #include <Inventor/nodes/SoSeparator.h>
- #include <Inventor/nodes/SoPerspectiveCamera.h>
- #include <Inventor/nodes/SoMaterial.h>
- #include <Inventor/nodes/SoDirectionalLight.h>
- #include <Inventor/nodes/SoCone.h>
- #include <Inventor/nodes/SoCube.h>
- #include <Inventor/nodes/SoTexture2.h>
- #include <Inventor/nodes/SoSwitch.h>
- #include <Inventor/nodes/SoPickStyle.h>
- #include <Inventor/manips/SoTrackballManip.h>
- #include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
- #include <Inventor/SoPickedPoint.h>
- #include <Inventor/sensors/SoTimerSensor.h>
-
- #include "ivcalc.h"
-
- // ****************************************
- // ****** xcalc code and variables ******
- // ****************************************
-
- const int MAXDISP = 10;
- #define STACKMAX 32
- static int opstack[STACKMAX];
- static int opsp;
- static double numstack[STACKMAX];
- static int numsp;
- static int entered=1; /* true if display contains a valid number.
- if==2, then use 'dnum', rather than the string
- stored in the display. (for accuracy)
- if==3, then error occurred, only CLR & AC work */
- /* entered seems to be overloaded - dmc */
- static int lift_enabled = 0; /* for rpn mode only */
-
- #define DEG 0 /* DRG mode. used for trig calculations */
- #define RAD 1
- #define GRAD 2
- static int CLR =0; /* CLR clears display. if 1, clears acc, also */
- static int Dpoint=0; /* to prevent using decimal pt twice in a # */
- static int clrdisp=1; /* if true clears display before entering # */
- static int lastop =kCLR;
- static int memop =kCLR;
- static int exponent=0;
- static double acc =0.0;
- static double dnum=0.0;
- static int rpn = 0;
- int errno = FALSE;
- int flagINV, flagPAREN, flagM, drgmode; /* display flags */
-
- #define XCALC_PRE_OP(keynum) if (pre_op(keynum)) return;
- #ifndef PI /* sometimes defined in math.h */
- #define PI 3.14159265358979
- #endif
- #define E 2.71828182845904
- static double drg2rad=PI/180.0; /* Conversion factors for trig funcs */
- static double rad2drg=180.0/PI;
- #define XCALC_MEMORY 10
- static double mem[XCALC_MEMORY] = { 0.0 };
-
-
- static void DrawDisplay();
- static void post_op();
- static void PushNum( double );
- static double PopNum();
- static void PushOp( int );
- static int PopOp();
- static void numeric( int );
- static void digit( int );
- static void subtract( int );
- static void add( int );
- static void divide( int );
- static void multiply( int );
- static void cosine( int );
- static void sine( int );
- static void tangent( int );
- static void inverse( int );
- static void e( int );
- static void pi( int );
- static void epower( int );
- static void factorial( int );
- static void naturalLog( int );
- static void logarithm( int );
- static void scientific( int );
- static void square( int );
- static void squareRoot( int );
- static void leftParen( int );
- static void rightParen( int );
- static void negate( int );
- static void clearit( int );
- static void decimal( int );
- static void degree( int );
- static void enter( int );
- static void equal( int );
- static void reciprocal( int );
- static void squareRoot( int );
- static void power( int );
- static void quit( int );
- static void off( int );
- static void back( int );
- static void twoop( int );
- static void oneop( int );
- static void sum( int );
- static void memf( int );
- static void twof( int );
- static int isopempty();
- static void parse_double (char *, char *, double *);
- static int priority( int );
- static void clearf();
- static void offf();
- static void ResetCalc();
- static void eef();
- static void invf();
- static void bkspf();
- static void decf();
- static void drgf();
- static void ClearStacks();
- static int pre_op( int );
- static void entrf();
- static void equf();
- static void negf();
- static void lparf();
- static void rparf();
- static void Quit();
- static void growCalc( int );
-
-
- // ****************************************
- // ****** IVcalc code and variables *****
- // ****************************************
-
- const int BTNDEPTH = 20;
- const float BTNSLOP = .20;
- float TIMERFREQ = 0.03;
- const float TEXTDEPTH = 8.0;
-
- /* AUDIO DEFINES */
- #define BUFFERSIZE 4000 /* Size of output sample buffer. */
-
-
- typedef struct Btn {
- int x;
- int y;
- float z;
- char *label;
- int colIndex;
- int btnVal;
- SoSeparator *bOrigin;
- void (*func)( int );
- };
-
- enum ActivateType { HIGHLIGHT, ANIMATE };
-
- struct PickData {
- int btnIndex;
- Boolean grow;
- SoPerspectiveCamera *camera;
- SoNode *root;
- SoTranslation *xlateBtn;
- SoTranslation *xlateKeypad;
- SoSwitch *xtraBtns;
- SoMaterial *mtlBtn;
- SoTransform *xformBase;
- SbViewportRegion vp;
- char *keyCode;
- enum ActivateType activateType;
- };
-
- struct Dim {
- float width;
- float height;
- float depth;
- };
-
- struct Pos {
- float x;
- float y;
- float z;
- };
-
- struct Col {
- float r;
- float g;
- float b;
- };
-
- const int NUMROWS = 5;
- const int NUMCOLS = 4;
- const int NUMXTRACOLS = 4;
-
- const float rowOff[] = { 0, -120, -240, -360, -480 };
- const float colOff[] = { 0, 120, 240, 360, -120, -240, -360, -480 };
- Col calcCols[20];
-
-
- Btn btns[] = {
- { 0, 0, 0, "AC", 1, -1, NULL, off },
- { 1, 0, 0, "CE", 1, kCLR, NULL, clearit },
- { 2, 0, 0, "G", 1, -1, NULL, growCalc },
- { 3, 0, 0, "/", 1, kDIV, NULL, divide },
- { 0, 1, 0, "7", 0, kSEVEN, NULL, digit },
- { 1, 1, 0, "8", 0, kEIGHT, NULL, digit },
- { 2, 1, 0, "9", 0, kNINE, NULL, digit },
- { 3, 1, 0, "*", 1, kMUL, NULL, multiply },
- { 0, 2, 0, "4", 0, kFOUR, NULL, digit },
- { 1, 2, 0, "5", 0, kFIVE, NULL, digit },
- { 2, 2, 0, "6", 0, kSIX, NULL, digit },
- { 3, 2, 0, "-", 1, kSUB, NULL, subtract },
- { 0, 3, 0, "3", 0, kTHREE, NULL, digit },
- { 1, 3, 0, "2", 0, kTWO, NULL, digit },
- { 2, 3, 0, "1", 0, kONE, NULL, digit },
- { 3, 3, 0, "+", 1, kADD, NULL, add },
- { 0, 4, 0, "0", 0, kZERO, NULL, digit },
- { 1, 4, 0, "+/-", 0, -1, NULL, negate },
- { 2, 4, 0, ".", 0, kDEC, NULL, decimal },
- { 3, 4, 0, "=", 1, kEQU, NULL, equal },
-
- { 4, 0, 0, "BS", 1, -1, NULL, back },
- { 4, 1, 0, "INV", 1, -1, NULL, inverse },
- { 4, 2, 0, "e", 1, kTHREE, NULL, e },
- { 4, 3, 0, "e^x", 1, kTWO, NULL, epower },
- { 4, 4, 0, "1/x", 1, kONE, NULL, reciprocal },
-
- { 5, 0, 0, ")", 1, kADD, NULL, rightParen },
- { 5, 1, 0, "sin", 1, kZERO, NULL, sine },
- { 5, 2, 0, "EE", 1, -1, NULL, scientific },
- { 5, 3, 0, "x^2", 1, kDEC, NULL, square },
- { 5, 4, 0, "x!", 1, kEQU, NULL, factorial },
-
- { 6, 0, 0, "(", 1, kADD, NULL, leftParen },
- { 6, 1, 0, "cos", 1, kZERO, NULL, cosine },
- { 6, 2, 0, "log", 1, -1, NULL, logarithm },
- { 6, 3, 0, "DRG", 1, kDEC, NULL, degree },
- { 6, 4, 0, "y^x", 1, kEQU, NULL, power },
-
- { 7, 0, 0, "Off", 1, kADD, NULL, quit },
- { 7, 1, 0, "tan", 1, kZERO, NULL, tangent },
- { 7, 2, 0, "ln", 1, -1, NULL, naturalLog },
- { 7, 3, 0, "pi", 1, kDEC, NULL, pi },
- { 7, 4, 0, "sqr", 1, kEQU, NULL, squareRoot }
- };
-
-
-
- static struct resources {
- Boolean maxWhizzy;
- Boolean textures;
- Boolean outputFile;
- Boolean niceBtns;
- Boolean niceBase;
- Boolean thickText;
- Boolean kbdAnimate;
- Boolean highlight;
- Boolean audio;
- Boolean saynum;
- Boolean help;
- String btnTextureFn;
- String baseTextureFn;
- String clickSndFn;
- String growSndFn;
- String roundBtnFn;
- String roundBaseFn;
- String sgiBtnFn;
- String baseCol;
- String digitBtnCol;
- String dispCol;
- String funcBtnCol;
- } appResources;
-
-
- #define offset(field) XtOffsetOf(struct resources, field)
- static XtResource Resources[] = {
- { "baseCol", "baseCol", XtRString, sizeof(String),
- offset(baseCol), XmRString, NULL },
- { "digitBtnCol", "digitBtnCol", XtRString, sizeof(String),
- offset(digitBtnCol), XmRString, NULL },
- { "funcBtnCol", "funcBtnCol", XtRString, sizeof(String),
- offset(funcBtnCol), XmRString, NULL },
- { "dispCol", "dispCol", XtRString, sizeof(String),
- offset(dispCol), XmRString, NULL },
- { "btnTextureFn", "BtnTextureFn", XtRString, sizeof(String),
- offset(btnTextureFn), XmRString, NULL },
- { "baseTextureFn", "BaseTextureFn", XtRString, sizeof(String),
- offset(baseTextureFn), XmRString, NULL },
- { "clickSndFn", "clickSndFn", XtRString, sizeof(String),
- offset(clickSndFn), XmRString, NULL },
- { "growSndFn", "growSndFn", XtRString, sizeof(String),
- offset(growSndFn), XmRString, NULL },
- { "roundBtnFn", "roundBtnFn", XtRString, sizeof(String),
- offset(roundBtnFn), XmRString, NULL },
- { "roundBaseFn", "roundBaseFn", XtRString, sizeof(String),
- offset(roundBaseFn), XmRString, NULL },
- { "sgiBtnFn", "sgiBtnFn", XtRString, sizeof(String),
- offset(sgiBtnFn), XmRString, NULL },
- {"maxWhizzy", "MaxWhizzy", XtRBoolean, sizeof(Boolean),
- offset(maxWhizzy), XtRString, "False"},
- {"niceBase", "NiceBase", XtRBoolean, sizeof(Boolean),
- offset(niceBase), XtRString, "True"},
- {"niceBtns", "NiceBtns", XtRBoolean, sizeof(Boolean),
- offset(niceBtns), XtRString, "False"},
- {"highlight", "highlight", XtRBoolean, sizeof(Boolean),
- offset(highlight), XtRString, "False"},
- {"kbdAnimate", "kbdAnimate", XtRBoolean, sizeof(Boolean),
- offset(kbdAnimate), XtRString, "False"},
- {"thickText", "ThickText", XtRBoolean, sizeof(Boolean),
- offset(thickText), XtRString, "False"},
- {"audio", "audio", XtRBoolean, sizeof(Boolean),
- offset(audio), XtRString, "False"},
- {"saynum", "saynum", XtRBoolean, sizeof(Boolean),
- offset(saynum), XtRString, "False"},
- {"textures", "Textures", XtRBoolean, sizeof(Boolean),
- offset(textures), XtRString, "False"},
- {"outputFile", "OutputFile", XtRBoolean, sizeof(Boolean),
- offset(outputFile), XtRString, "False"},
- {"help", "Help", XtRBoolean, sizeof(Boolean),
- offset(help), XtRString, "False"}
- };
- #undef offset
-
-
- static XrmOptionDescRec optionDesc[] = {
- { "-maxWhizzy", "maxWhizzy", XrmoptionNoArg, (caddr_t) "True" },
- { "-niceBtns", "niceBtns", XrmoptionNoArg, (caddr_t) "True" },
- { "-niceBase", "niceBase", XrmoptionNoArg, (caddr_t) "True" },
- { "-textures", "textures", XrmoptionNoArg, (caddr_t) "True" },
- { "-outputFile", "outputFile", XrmoptionNoArg, (caddr_t) "True" },
- { "-thickText", "thickText", XrmoptionNoArg, (caddr_t) "True" },
- { "-audio", "audio", XrmoptionNoArg, (caddr_t) "True" },
- { "-kbdAnimate", "kbdAnimate", XrmoptionNoArg, (caddr_t) "True" },
- { "-highlight", "highlight", XrmoptionNoArg, (caddr_t) "True" },
- { "-help", "help", XrmoptionNoArg, (caddr_t) "True"}};
-
-
-
- static String fallbackResources[] = {
- "*digitBtnCol: 0.25 0.26 0.09",
- "*funcBtnCol: 0.00 0.26 0.60",
- "*baseCol: 0.67 0.35 0.00",
- "*dispCol: 0.59 0.59 0.59",
- "*btnTextureFn: corinth.rgb",
- "*baseTextureFn: redmar.rgb",
- "*clickSndFn: drm_clave.aiff",
- "*growSndFn: belltree_up2.aiff",
- "*roundBtnFn: cbutton.iv",
- "*roundBaseFn: cbase.iv",
- "*sgiBtnFn: sgigrow.iv",
- "*sgiMode: True",
- "*useSchemes: all",
- NULL
- };
-
-
-
- class TextReg {
-
- char *dispStr;
- double number;
- char tmp[32];
-
- public:
- TextReg(char *str)
- {
- dispStr = new(char [80]);
- setValue( str );
- }
-
- void clear()
- {
- number = 0.0;
- *dispStr = '\0';
- }
-
-
- void addChar(char ch)
- {
- int sLen = strlen(dispStr);
- if ( sLen != MAXDISP ) {
- dispStr[sLen] = ch;
- dispStr[sLen + 1] = '\0';
- }
- }
-
-
- int getLength() { return( strlen( dispStr )); }
-
- void setValue( char *str ) { strcpy( dispStr, str ); }
-
- char * getValue() { return( dispStr ); }
-
- char getChar( int index ) { return( dispStr[index] ); }
-
- void removeHead() { strcpy( dispStr, dispStr + 1 ); }
-
- void addHead( char ch )
- {
- sprintf( tmp, "%c%s", ch, dispStr );
- strcpy( dispStr, tmp );
- }
-
- void removeTail() { dispStr[strlen(dispStr)-1] = '\0'; }
- void replaceChar( int index, char ch ) { dispStr[index] = ch; }
-
- void display( SoText3 *text ) { text->string.setValue( dispStr ); }
- };
-
-
- Dim baseDim = { 640, 800, 80 };
- Dim dispDim = { 530, 125, 10 };
- Dim btnDim = { 100, 100, 20 };
- Dim keypadDim;
- Dim textDim = { 100, 100, 20 };
- Pos basePos = { 0, 0, 0 };
- Pos dispPos;
- Pos ansPos;
- Pos keypadPos;
- float xSpacing = 0;
- float ySpacing = 0;
- int numBtns;
- char dispStr[80];
- TextReg textReg( "0." );
- const float dispFontSize = 0.5 * dispDim.height;
- const float btnFontScale = 0.5;
- SoText3 *textDisp;
- Bool stillPushing = FALSE;
- Bool stillGrowing = FALSE;
- SoXtExaminerViewer *viewer;
- XtAppContext appContext;
- PickData pickData;
- float textThickness;
- int numBasicBtns = 20;
- int numXtraBtns = 20;
-
- ALport audioport;
-
- static void usage();
- static void handlePickCB( void *, SoEventCallback * );
- static void handleKbdCB( void *, SoEventCallback * );
- static void btnAnimationCB( void *, SoSensor * );
- static void growCalcCB( void *, SoSensor * );
- static void initAppAndResources( int *, char **, Widget & );
- static void buildBtns( SoGroup *, PickData & );
- static SoSeparator * buildButton( int, SoMaterial *, SoFont *, SoTranslation *,
- SoTexture2 *, SoNode * );
- static SoSeparator * buildBase();
- static SoSeparator * buildDisplay();
- static void printPath( const SoPath * );
- static void activateBtn( PickData * );
-
- static void playSoundFn( char * );
- static void playSnd( void * );
- static void audioInit();
-
-
-
-
- main( int argc, char **argv )
- {
- Widget appWindow;
- initAppAndResources( &argc, argv, appWindow );
-
- SoSeparator *root = new SoSeparator;
- SoPerspectiveCamera *camera = new SoPerspectiveCamera;
- root->ref();
- root->addChild( camera );
- pickData.camera = camera;
-
- SoTransform *xform = new SoTransform;
- xform->rotation.setValue( SbVec3f( 1, 0, 0 ), -M_PI/6 );
- root->addChild(xform);
-
- SoEventCallback *eventCB = new SoEventCallback;
- root->addChild( eventCB );
-
- SoSeparator *calcBaseGroup = new SoSeparator;
- calcBaseGroup->addChild( buildBase() );
- calcBaseGroup->addChild( buildDisplay() );
-
- root->addChild( calcBaseGroup );
-
- pickData.grow = False;
- pickData.root = root;
- buildBtns(calcBaseGroup, pickData);
-
- viewer = new SoXtExaminerViewer( appWindow );
- viewer->setSceneGraph( root );
- viewer->setTitle( "IVcalc" );
- viewer->setIconTitle( "IVcalc" );
- viewer->setSize( SbVec2s( 300, 350 ));
- viewer->setViewing( FALSE );
- viewer->setDecoration( FALSE );
-
- pickData.vp = viewer->getViewportRegion();
- camera->viewAll( root, pickData.vp );
- camera->position.setValue( 0, 0, 1100 );
-
- viewer->show();
-
- SbVec2s winSize = viewer->getSize();
- pickData.root = root;
-
- eventCB->addEventCallback( SoMouseButtonEvent::getClassTypeId(),
- handlePickCB, &pickData );
-
- eventCB->addEventCallback( SoKeyboardEvent::getClassTypeId(),
- handleKbdCB, &pickData );
-
- if ( appResources.outputFile ) {
- SoOutput *outfile = new SoOutput;
- if ( outfile->openFile( "calc.iv" )) {
- SoWriteAction *writeAction = new SoWriteAction( outfile );
- writeAction->apply( root );
- }
- }
-
- if ( appResources.audio )
- audioInit();
-
- SoXt::show( appWindow ); // Display main window
- SoXt::mainLoop(); // Main Inventor event loop
- }
-
-
-
- static void
- initAppAndResources( int *argc, char **argv, Widget &appWindow )
- {
- #ifdef SYSTYPE_SVR4
- int *avalue = argc;
- #else
- Cardinal *avalue = (Cardinal *)argc;
- #endif
-
- appWindow = XtVaAppInitialize( &appContext, "IVcalc",
- optionDesc, XtNumber(optionDesc),
- avalue, argv,
- fallbackResources,
- NULL);
-
- if ( *argc > 1 )
- usage();
-
- SoXt::init( appWindow ); // pass top Level widget
- if ( appWindow == NULL ) exit( 1 );
-
-
- XtGetApplicationResources(appWindow, (XtPointer)&appResources, Resources,
- XtNumber(Resources), (ArgList) NULL, NULL);
-
- if ( appResources.help )
- usage();
-
- sscanf(appResources.digitBtnCol, "%f %f %f", &calcCols[0].r, &calcCols[0].g,
- &calcCols[0].b );
- sscanf( appResources.funcBtnCol, "%f %f %f", &calcCols[1].r, &calcCols[1].g,
- &calcCols[1].b );
- sscanf( appResources.baseCol, "%f %f %f", &calcCols[2].r, &calcCols[2].g,
- &calcCols[2].b );
- sscanf( appResources.dispCol, "%f %f %f", &calcCols[3].r, &calcCols[3].g,
- &calcCols[3].b );
-
- if ( appResources.maxWhizzy || appResources.thickText )
- textThickness = TEXTDEPTH;
- else
- textThickness = 1.0;
- }
-
-
-
- static SoSeparator *
- buildDisplay()
- {
- SoSeparator *calcDisp = new SoSeparator;
-
- SoMaterial *mtlDisp = new SoMaterial;
- mtlDisp->diffuseColor.setValue( calcCols[3].r, calcCols[3].g,
- calcCols[3].b );
- calcDisp->addChild( mtlDisp );
-
- SoTranslation *xlateDisp = new SoTranslation;
- calcDisp->addChild( xlateDisp );
-
- SoCube *answerDisplay = new SoCube;
- answerDisplay->width = dispDim.width;
- answerDisplay->height = dispDim.height;
- answerDisplay->depth = dispDim.depth;
- calcDisp->addChild( answerDisplay );
-
- dispPos.x = 0;
- dispPos.y = baseDim.height / 2 - dispDim.height / 2 - baseDim.height * 0.05;
- dispPos.z = ( baseDim.depth / 2 ) + ( dispDim.depth / 2 );
- xlateDisp->translation.setValue(SbVec3f( dispPos.x, dispPos.y, dispPos.z ));
-
- SoSeparator *ansText = new SoSeparator;
-
- SoPickStyle *pickStyle = new SoPickStyle;
- pickStyle->style.setValue( SoPickStyle::UNPICKABLE );
- ansText->addChild( pickStyle );
-
- SoMaterial *mtlText = new SoMaterial;
- mtlText->diffuseColor.setValue( 0.0, 0.0, 0.0 );
- ansText->addChild( mtlText );
-
- SoFont *font = new SoFont;
- font->name.setValue( "Utopia-Bold" );
- font->size = dispFontSize;
- ansText->addChild( font );
- SoTranslation *xlateText = new SoTranslation;
- ansText->addChild( xlateText );
-
- textDisp = new SoText3;
-
- if ( appResources.maxWhizzy || appResources.thickText )
- textDisp->parts.setValue( SoText3::FRONT | SoText3::SIDES );
- else
- textDisp->parts.setValue( SoText3::FRONT );
-
- SoScale *scaleText = new SoScale;
- scaleText->scaleFactor.setValue( SbVec3f( 1.0, 1.6, textThickness ));
- ansText->addChild( scaleText );
-
- textDisp->justification.setValue( SoText3::RIGHT );
- textReg.display( textDisp );
- ansText->addChild( textDisp );
- calcDisp->addChild( ansText );
-
- // const SbViewportRegion &vp = viewer->getViewportRegion();
- SoGetBoundingBoxAction *bboxAction = new SoGetBoundingBoxAction( pickData.vp );
- bboxAction->apply( ansText );
- bboxAction->getBoundingBox().getSize( textDim.width, textDim.height,
- textDim.depth );
- ansPos.x = ( dispDim.width / 2 ) * 0.9;
- ansPos.y = -textDim.height / 2;
- ansPos.z = ( dispDim.depth / 2 ) + ( textDim.depth / 2 ) + textThickness;
- xlateText->translation.setValue(SbVec3f( ansPos.x, ansPos.y , ansPos.z ));
-
- return( calcDisp );
- }
-
-
- static SoSeparator *
- buildBase()
- {
- SoSeparator *calcBase = new SoSeparator;
-
- SoTransform *xform = new SoTransform;
- calcBase->addChild(xform);
- pickData.xformBase = xform;
-
- SoMaterial *mtlBase = new SoMaterial;
- mtlBase->diffuseColor.setValue( calcCols[2].r, calcCols[2].g,
- calcCols[2].b );
- mtlBase->specularColor.setValue(.6, .6, .6);
- mtlBase->shininess.setValue(.5);
- calcBase->addChild( mtlBase );
-
- SoTexture2 *baseTxtr;
- if ( appResources.maxWhizzy || appResources.textures ) {
- baseTxtr = new SoTexture2;
- baseTxtr->filename.setValue( appResources.baseTextureFn );
- baseTxtr->model.setValue( SoTexture2::MODULATE );
- calcBase->addChild( baseTxtr );
- }
-
- SoNode *baseShape;
- if ( appResources.maxWhizzy || appResources.niceBase ) {
- SoInput myfile;
- myfile.openFile( appResources.roundBaseFn );
- SoDB::read( &myfile, baseShape );
- }
- else {
- baseShape = new SoCube;
- ((SoCube *)baseShape)->width = baseDim.width;
- ((SoCube *)baseShape)->height = baseDim.height;
- ((SoCube *)baseShape)->depth = baseDim.depth;
- }
- calcBase->addChild( baseShape );
- return( calcBase );
- }
-
-
- static void
- buildBtns( SoGroup *calcBase, PickData &pickData )
- {
- SoSeparator *keypad = new SoSeparator;
- SoNode *tmpBtn;
- SoTexture2 *texture;
-
- if ( appResources.maxWhizzy || appResources.niceBtns ) {
- SoInput myfile;
- myfile.openFile( appResources.roundBtnFn );
- SoDB::read( &myfile, tmpBtn );
- }
- else {
- tmpBtn = new SoCube;
- ((SoCube *)tmpBtn)->width = btnDim.width;
- ((SoCube *)tmpBtn)->height = btnDim.height;
- ((SoCube *)tmpBtn)->depth = btnDim.depth;
- }
-
- xSpacing = BTNSLOP * btnDim.width;
- ySpacing = BTNSLOP * btnDim.height;
-
- SoTranslation *xlateBtns = new SoTranslation;
-
- keypadDim.width = NUMCOLS * btnDim.width - (( NUMCOLS - 1 ) * xSpacing );
- keypadPos.x = ( baseDim.width - ( NUMCOLS * btnDim.width ) -
- (( NUMCOLS - 1 ) * xSpacing )) / 2 - ( baseDim.width / 2 ) +
- ( btnDim.width / 2 );
- keypadDim.height = NUMROWS * btnDim.height - (( NUMROWS - 1 ) * ySpacing);
- float offsetFromDisp = dispPos.y - dispDim.height / 2;
- keypadPos.y = ( keypadDim.height / 2 ) - ( baseDim.height * 0.05 );
- keypadPos.z = baseDim.depth / 2 + btnDim.depth / 2;
-
- xlateBtns->translation.setValue(SbVec3f( keypadPos.x, keypadPos.y,
- keypadPos.z ));
- keypad->addChild( xlateBtns );
- pickData.xlateKeypad = xlateBtns;
-
- if ( appResources.maxWhizzy || appResources.textures ) {
- texture = new SoTexture2;
- texture->filename.setValue( appResources.btnTextureFn );
- texture->model.setValue( SoTexture2::MODULATE );
- }
-
- SoSeparator *nodeText = new SoSeparator;
- SoMaterial *mtlText = new SoMaterial;
- mtlText->diffuseColor.setValue( 1.0, 1.0, 1.0 ); // white
-
- SoFont *font = new SoFont;
- font->name.setValue( "Utopia-Bold" );
- float btnFontSize = btnDim.height * btnFontScale;
- font->size = btnFontSize;
-
-
- SoTranslation *xlateText = new SoTranslation;
- xlateText->translation.setValue( SbVec3f( 0, -btnFontSize / 2,
- btnDim.depth/2 + textThickness ));
-
- SoSwitch *basicBtns = new SoSwitch;
- for ( int i = 0; i < numBasicBtns; i++ )
- basicBtns->addChild( buildButton( i, mtlText, font, xlateText, texture,
- tmpBtn ));
- basicBtns->whichChild.setValue( SO_SWITCH_ALL );
-
- SoSwitch *xtraBtns = new SoSwitch;
- for ( i = numBasicBtns; i < numBasicBtns + numXtraBtns; i++ )
- xtraBtns->addChild( buildButton( i, mtlText, font, xlateText, texture,
- tmpBtn ));
- xtraBtns->whichChild.setValue( SO_SWITCH_NONE );
- pickData.xtraBtns = xtraBtns;
-
- numBtns = numBasicBtns + numXtraBtns;
- keypad->addChild( basicBtns );
- keypad->addChild( xtraBtns );
- calcBase->addChild( keypad );
- }
-
-
-
- static SoSeparator *
- buildButton( int i, SoMaterial *mtlText, SoFont *font,
- SoTranslation *xlateText, SoTexture2 *texture, SoNode *tmpBtn )
- {
- SoSeparator *groupBtn = new SoSeparator;
- SoSeparator *compBtn = new SoSeparator;
- SoNode *tmpLabel;
-
-
- SoInput myfile;
- myfile.openFile( appResources.sgiBtnFn );
- SoDB::read( &myfile, tmpLabel );
-
- SoTranslation *xlateBtn = new SoTranslation;
- xlateBtn->translation.setValue( SbVec3f( colOff[ btns[ i ].x ],
- rowOff[ btns[ i ].y ],
- btns[i].z));
-
- SoLabel *labelBtn = new SoLabel;
- labelBtn->label = btns[i].label;
-
- SoMaterial *mtlBtn = new SoMaterial;
- mtlBtn->diffuseColor.setValue( calcCols[ btns[ i ].colIndex ].r,
- calcCols[ btns[ i ].colIndex ].g,
- calcCols[ btns[ i ].colIndex ].b );
- pickData.mtlBtn = mtlBtn;
- mtlBtn->specularColor.setValue(.6, .6, .6);
- mtlBtn->shininess.setValue(.5);
- SoText3 *text = new SoText3;
- if ( appResources.maxWhizzy || appResources.thickText )
- text->parts.setValue( SoText3::FRONT | SoText3::SIDES );
- else
- text->parts.setValue( SoText3::FRONT );
-
- SoScale *scaleText = new SoScale;
- scaleText->scaleFactor.setValue( SbVec3f( 1.0, 1.5, textThickness ));
-
- SoPickStyle *pickStyle = new SoPickStyle;
- pickStyle->style.setValue( SoPickStyle::UNPICKABLE );
-
- text->justification.setValue( SoText3::CENTER );
- text->string.setValue( btns[i].label );
- SoSeparator *textBtn = new SoSeparator;
- textBtn->addChild( pickStyle );
- textBtn->addChild( mtlText );
- textBtn->addChild( font );
- textBtn->addChild( xlateText );
- if ( strncmp( btns[i].label, "G", 1 )) {
- textBtn->addChild( scaleText );
- textBtn->addChild( text );
- }
- else {
- SoTranslation *transLogo = new SoTranslation;
- transLogo->translation.setValue( SbVec3f( -15, 35, 0 ));
- textBtn->addChild( transLogo );
- textBtn->addChild( tmpLabel );
- }
-
- compBtn->renderCaching.setValue( SoSeparator::ON );
- compBtn->addChild( labelBtn );
- compBtn->addChild( mtlBtn );
- compBtn->addChild( textBtn );
- if ( appResources.maxWhizzy || appResources.textures )
- compBtn->addChild( texture );
- compBtn->addChild( tmpBtn );
- groupBtn->addChild( xlateBtn );
- groupBtn->addChild( compBtn );
- btns[i].bOrigin = groupBtn;
- return( groupBtn );
- }
-
-
-
- static void
- usage()
- {
- static char *help_message[] = {
- "where options include:",
- " -niceBtns rounded buttons",
- " -textures apply textures to buttons and base",
- " -outputFile write out Inventor scenegraph to calc.iv",
- " -thickText 3D text with exagerated depth",
- " -audio button sounds, etc",
- " -kbdAnimate buttons are animated when kbd input used",
- " -maxWhizzy turn on all extra enhancements (except kbdAnimate)",
- " -help print this usage message",
- NULL};
- char **s;
-
- cout << "usage:\t [-options ...]" << endl;
- for (s= help_message; *s; s++)
- cout << *s << endl;
- cout << endl;
- exit(0);
- }
-
-
- static void
- handlePickCB(void *userData, SoEventCallback *eventCB)
- {
- static Boolean firstCh = True;
- PickData *pickData = (PickData *) userData;
-
- const SoEvent *event = eventCB->getEvent();
- if ( SO_MOUSE_PRESS_EVENT( event, BUTTON1 )) {
- const SoPickedPoint *ePP = eventCB->getPickedPoint();
- if ( ePP == NULL )
- return;
- const SoPath *ePath = ePP->getPath();
- if ( ePath == NULL )
- return;
- for ( int i = 0; i < numBtns; i++ ) {
- if ( ePath->containsNode( btns[i].bOrigin )) {
- if ( stillPushing )
- return;
- eventCB->setHandled();
- pickData->activateType = ANIMATE;
- pickData->btnIndex = i;
- activateBtn( pickData );
- break;
- }
- }
- }
- }
-
-
-
- static void
- handleKbdCB(void *userData, SoEventCallback *eventCB)
- {
- PickData *pickData = (PickData *) userData;
- int keyTag;
- static Boolean shiftFlag = False;
- const SoKeyboardEvent *event = (SoKeyboardEvent *)eventCB->getEvent();
-
- // set and unset shiftFlag to denote shift key usage and
- // throw away initail presses of keys and only act on the release of other keys
- if ( event->isKeyPressEvent( event, SoKeyboardEvent::LEFT_SHIFT ) ||
- event->isKeyPressEvent( event, SoKeyboardEvent::RIGHT_SHIFT )) {
- shiftFlag = True;
- eventCB->setHandled();
- return;
- }
- else if ( event->isKeyReleaseEvent( event, SoKeyboardEvent::LEFT_SHIFT ) ||
- event->isKeyReleaseEvent( event, SoKeyboardEvent::RIGHT_SHIFT )) {
- shiftFlag = False;
- eventCB->setHandled();
- return;
- }
- else if ( event->isKeyPressEvent( event, SoKeyboardEvent::ANY )) {
- eventCB->setHandled();
- return;
- }
- else if ( event->isKeyReleaseEvent( event, SoKeyboardEvent::ANY ))
- eventCB->setHandled();
-
-
- switch ( event->getKey() ) {
- case SoKeyboardEvent::PAD_0:
- case SoKeyboardEvent::NUMBER_0: { keyTag = kZERO; break; }
- case SoKeyboardEvent::PAD_1:
- case SoKeyboardEvent::NUMBER_1: { keyTag = kONE; break; }
- case SoKeyboardEvent::PAD_2:
- case SoKeyboardEvent::NUMBER_2: { keyTag = kTWO; break; }
- case SoKeyboardEvent::PAD_3:
- case SoKeyboardEvent::NUMBER_3: { keyTag = kTHREE; break; }
- case SoKeyboardEvent::PAD_4:
- case SoKeyboardEvent::NUMBER_4: { keyTag = kFOUR; break; }
- case SoKeyboardEvent::PAD_5:
- case SoKeyboardEvent::NUMBER_5: { keyTag = kFIVE; break; }
- case SoKeyboardEvent::PAD_6:
- case SoKeyboardEvent::NUMBER_6: { keyTag = kSIX; break; }
- case SoKeyboardEvent::PAD_7:
- case SoKeyboardEvent::NUMBER_7: { keyTag = kSEVEN; break; }
- case SoKeyboardEvent::PAD_8:
- case SoKeyboardEvent::NUMBER_8: { if ( shiftFlag )
- keyTag = kMUL;
- else
- keyTag = kEIGHT; break; }
- case SoKeyboardEvent::PAD_9:
- case SoKeyboardEvent::NUMBER_9: { keyTag = kNINE; break; }
- case SoKeyboardEvent::PAD_ADD: { keyTag = kADD; break; }
- case SoKeyboardEvent::PAD_SUBTRACT:
- case SoKeyboardEvent::MINUS: { keyTag = kSUB; break; }
- case SoKeyboardEvent::PAD_MULTIPLY: { keyTag = kMUL; break; }
- case SoKeyboardEvent::PAD_DIVIDE:
- case SoKeyboardEvent::SLASH: { keyTag = kDIV; break; }
- case SoKeyboardEvent::EQUAL: { if ( shiftFlag )
- keyTag = kADD;
- else
- keyTag = kEQU; break; }
- case SoKeyboardEvent::PAD_ENTER:
- case SoKeyboardEvent::ENTER: { keyTag = kEQU; break; }
- case SoKeyboardEvent::PAD_PERIOD:
- case SoKeyboardEvent::PERIOD: { keyTag = kDEC; break; }
- case SoKeyboardEvent::BACKSPACE:
- case SoKeyboardEvent::DELETE: { keyTag = kBKSP; break; }
- case SoKeyboardEvent::C: { keyTag = kCLR; break; }
- case SoKeyboardEvent::Q: { Quit(); break; }
- }
-
- for ( int i = 0; i < numBtns; i++ ) {
- if ( keyTag == btns[i].btnVal ) {
- if ( appResources.maxWhizzy || appResources.audio )
- playSoundFn( appResources.clickSndFn );
-
- if ( stillPushing )
- return;
- if ( appResources.kbdAnimate )
- pickData->activateType = ANIMATE;
- else
- pickData->activateType = HIGHLIGHT;
- pickData->btnIndex = i;
- activateBtn( pickData );
- break;
- }
- }
- }
-
-
-
-
- static void
- activateBtn( PickData *pickData )
- {
- static SoTimerSensor *timer = new SoTimerSensor( btnAnimationCB, pickData );
-
- SoSeparator *topNode = btns[pickData->btnIndex].bOrigin;
- for (int j = 0; j < topNode->getNumChildren(); j++) {
- if ( topNode->getChild( j )->getTypeId() ==
- SoTranslation::getClassTypeId())
- pickData->xlateBtn = (SoTranslation *)topNode->getChild( j );
- }
-
- btns[pickData->btnIndex].func( btns[pickData->btnIndex].btnVal );
-
- if ( pickData->activateType == ANIMATE || appResources.highlight ) {
- timer->setInterval( TIMERFREQ ); // timer to go off every 1/10 sec
- timer->schedule();
- }
- else
- textReg.display( textDisp );
- }
-
-
-
- static void
- printPath(const SoPath *path)
- {
- for ( int i = 0; i < path->getLength(); i++ )
- cout << path->getNode( i )->getTypeId().getName().getString() << endl;
- }
-
-
-
- static void
- growCalc( int )
- {
- static SoTimerSensor *timer = new SoTimerSensor( growCalcCB, &pickData );
-
- if ( stillGrowing )
- return;
-
- stillGrowing = True;
-
- if ( pickData.grow ) {
- pickData.grow = False;
- pickData.xtraBtns->whichChild.setValue( SO_SWITCH_NONE );
- }
- else {
- pickData.grow = True;
- pickData.camera->viewAll( pickData.root, pickData.vp );
- }
-
- if ( appResources.maxWhizzy || appResources.audio )
- playSoundFn( appResources.growSndFn );
-
- timer->setInterval( TIMERFREQ ); // timer to go off every 1/100 sec
- timer->schedule();
- }
-
-
-
- static void
- growCalcCB( void *userData, SoSensor *sensor )
- {
- const int ANIMTIMES = 10;
- PickData *pickData = (PickData *) userData;
- SoTimerSensor *timer = (SoTimerSensor *) sensor;
- static float scaleInc = ( NUMXTRACOLS * ( btnDim.width +
- ( BTNSLOP * btnDim.width ))
- / baseDim.width ) / ANIMTIMES;
- static float growInc = ( scaleInc * baseDim.width ) / 2;
- static float scaleFactor;
- static int counter = 0;
-
-
- if ( ++counter < ANIMTIMES + 1 ) {
- if ( pickData->grow ) {
- scaleFactor = 1 + scaleInc * counter;
- keypadPos.x += growInc;
- }
- else {
- scaleFactor = 1 + (scaleInc * ANIMTIMES) -
- scaleInc * counter;
- keypadPos.x -= growInc;
- }
-
- pickData->xformBase->scaleFactor.setValue( SbVec3f( scaleFactor, 1, 1 ));
- pickData->xlateKeypad->translation.setValue(SbVec3f(keypadPos.x,
- keypadPos.y,
- keypadPos.z ));
- viewer->render();
- }
- else {
- if ( pickData->grow ) {
- pickData->xtraBtns->whichChild.setValue( SO_SWITCH_ALL );
- baseDim.width *= scaleFactor;
- }
- else {
- pickData->camera->viewAll( pickData->root, pickData->vp );
- baseDim.width *= 1 / ( 1 + scaleInc * ANIMTIMES );
- }
- stillGrowing = False;
- counter = 0;
- timer->unschedule();
- }
- }
-
-
-
- static void
- btnAnimationCB( void *userData, SoSensor *sensor)
- {
- const int ANIMTIMES = 2;
- PickData *pickData = (PickData *) userData;
- SoTimerSensor *timer = (SoTimerSensor *) sensor;
- static SbVec3f curTrans;
- static int counter = ANIMTIMES;
- static Boolean isHighlighted = False;
- static SoTranslation *btnTrans = new SoTranslation;
-
- if ( pickData->activateType == HIGHLIGHT ) {
- if ( isHighlighted ) {
- isHighlighted = False;
- stillPushing = False;
- int i = pickData->btnIndex;
- pickData->mtlBtn->diffuseColor.setValue( calcCols[ btns[i].colIndex ].r,
- calcCols[ btns[i].colIndex ].g,
- calcCols[ btns[i].colIndex ].b );
- timer->unschedule();
- }
- else {
- isHighlighted = True;
- stillPushing = True;
- pickData->mtlBtn->diffuseColor.setValue( .8, 0, 0 );
- }
- }
-
- switch ( counter ) {
- case 0:
- timer->unschedule();
- counter = ANIMTIMES;
- stillPushing = FALSE;
- viewer->setAutoRedraw( TRUE );
- return;
- case 1:
- curTrans[2] = 0;
- counter--;
- if ( appResources.maxWhizzy || appResources.audio )
- playSoundFn( appResources.clickSndFn );
- textReg.display( textDisp );
- break;
- case ANIMTIMES:
- btnTrans = pickData->xlateBtn;
- curTrans = btnTrans->translation.getValue();
- stillPushing = TRUE;
- viewer->setAutoRedraw( FALSE );
- default:
- curTrans[2] = -BTNDEPTH + 2;
- counter--;
- break;
- }
-
- btnTrans->translation.setValue( curTrans );
- viewer->render();
- }
-
-
-
- static void
- audioInit()
- {
- }
-
-
- static void
- playSoundFn( char *sndfn )
- {
- static char *playaifc = "playaifc ";
- static char *devnull = " > /dev/null";
- char playStr[ 80 ];
-
- strcpy( playStr, playaifc );
- strcat( playStr, sndfn );
- strcat( playStr, devnull );
-
- sproc( playSnd, PR_SALL, playStr );
- }
-
-
-
- static void
- playSnd( void *playStr )
- {
- system( (char *)playStr );
- }
-
-
-
- // ****************************************
- // ****** xcalc code ******
- // ****************************************
-
- /* The following routines are based on code from the MIT X11 sample client
- * code for xcalc.
- *
- * xcalc.c - a hand calculator for the X Window system
- *
- * Copyright 1989 by the Massachusetts Institute of Technology
- */
-
-
- static void
- digit( int keynum )
- {
- XCALC_PRE_OP( keynum );
- numeric( keynum );
- post_op();
- }
-
-
- static void
- numeric( int keynum )
- {
- if ( clrdisp ) {
- textReg.clear();
- exponent = Dpoint = 0;
- // if (rpn && entered==2)
- // PushNum(dnum);
- if (rpn & lift_enabled)
- PushNum(dnum);
- }
-
- if ( textReg.getLength() >= MAXDISP )
- return;
-
- switch ( keynum ) {
- case kONE: textReg.addChar( '1' ); break;
- case kTWO: textReg.addChar( '2' ); break;
- case kTHREE: textReg.addChar( '3' ); break;
- case kFOUR: textReg.addChar( '4' ); break;
- case kFIVE: textReg.addChar( '5' ); break;
- case kSIX: textReg.addChar( '6' ); break;
- case kSEVEN: textReg.addChar( '7' ); break;
- case kEIGHT: textReg.addChar( '8' ); break;
- case kNINE: textReg.addChar( '9' ); break;
- case kZERO: textReg.addChar( '0' ); break;
- }
-
- DrawDisplay();
- if ( clrdisp && keynum != kZERO )
- clrdisp = 0; /*no leading 0s*/
- entered = 1;
- lift_enabled = 0;
- }
-
-
- static void
- post_op()
- {
- if (errno) {
- textReg.setValue( "error" );
- DrawDisplay();
- entered=3;
- errno=0;
- }
- }
-
-
- static void
- effectUpdate()
- {
- textReg.display( textDisp );
- }
-
- static void
- DrawDisplay()
- {
- //display is updated in btnAnimationCB so as to try to have
- //the new numbers appear as the button reaches the bottom of its press
- }
-
-
- static void
- twof( int )
- {
- }
-
-
- static void
- memf( int keynum )
- {
- memop = keynum;
- char *tmpStr;
- if (entered==1) {
- tmpStr = textReg.getValue();
- parse_double( tmpStr, "%lf", &dnum );
- }
- entered = 2;
- clrdisp++;
- lift_enabled = 0;
- }
-
-
- static void
- oneop( int keynum )
- {
- int i,j;
- double dtmp;
-
- char *tmpStr = textReg.getValue();
- if (entered==1) {
- parse_double( tmpStr, "%lf", &dnum );
- }
- entered = 2;
-
- switch ( keynum ) { /* do the actual math fn. */
- case kE: if (rpn && memop != kENTR) PushNum(dnum); dnum=E; break;
- case kPI: if (rpn && memop != kENTR) PushNum(dnum); dnum=PI; break;
- case kRECIP: dnum=1.0/dnum; break;
- case kSQR: flagINV = !flagINV; /* fall through to */
- case kSQRT: if (flagINV) dnum=dnum*dnum;
- else dnum=sqrt(dnum);
- break;
- case k10X: flagINV = !flagINV; /* fall through to */
- case kLOG: if (flagINV) dnum=pow(10.0,dnum);
- else dnum=log10(dnum);
- break;
- case kEXP: flagINV = !flagINV; /* fall through to */
- case kLN: if (flagINV) dnum=exp(dnum);
- else dnum=log(dnum);
- break;
- case kSIN: if (flagINV) dnum=asin(dnum)*rad2drg;
- else dnum=sin(dnum*drg2rad);
- break;
- case kCOS: if (flagINV) dnum=acos(dnum)*rad2drg;
- else dnum=cos(dnum*drg2rad);
- break;
- case kTAN: if (flagINV) dnum=atan(dnum)*rad2drg;
- else dnum=tan(dnum*drg2rad);
- break;
- case kSTO: mem[0]=dnum; flagM=!(mem[0]==0.0); break;
- case kRCL: if (rpn && lift_enabled) PushNum(dnum);
- dnum=mem[0]; flagM=!(mem[0]==0.0); break;
- case kSUM: mem[0]+=dnum; flagM=!(mem[0]==0.0); break;
- case kEXC: dtmp=dnum; dnum=mem[0]; mem[0]=dtmp;
- flagM=!(mem[0]==0.0); break;
- case kFACT: if (floor(dnum)!=dnum || dnum<0.0 || dnum>500.0) {
- textReg.setValue( "stack error" );
- entered=3;
- break;
- }
- i=(int) (floor(dnum));
- for ( j = 1, dnum = 1.0; j <= i; j++ )
- dnum *= (float) j;
- break;
- }
-
- if ( entered == 3 ) { /* error */
- DrawDisplay();
- return;
- }
-
- entered=2;
- clrdisp=1;
- flagINV=0;
- lift_enabled = 1;
-
- sprintf( tmpStr, "%.8g", dnum );
- textReg.setValue( tmpStr );
- DrawDisplay();
- }
-
-
- static void
- twoop( int keynum )
- {
-
- if (flagINV) {
- flagINV=0;
- DrawDisplay();
- }
-
- if ( !entered ) { /* something like "5+*" */
- if ( isopempty() == 0 )
- PopOp(); /* replace the prev op */
- PushOp( keynum ); /* with the new one */
- return;
- }
-
- char *tmpStr;
- if (entered == 1) {
- tmpStr = textReg.getValue();
- parse_double( tmpStr,"%lf",&dnum );
- }
-
- clrdisp = CLR = 1;
- entered = Dpoint = exponent = 0;
-
- if ( isopempty() == 0 ) { /* there was a previous op */
- lastop = PopOp(); /* get it */
-
- if ( lastop == kLPAR ) { /* put it back */
- PushOp( kLPAR );
- PushOp( keynum );
- PushNum( dnum );
- return;
- }
-
- /* now, if the current op (keynum) is of
- higher priority than the lastop, the current
- op and number are just pushed on top
- Priorities: (Y^X) > *,/ > +,- */
-
- if (priority( keynum ) > priority( lastop )) {
- PushNum( dnum );
- PushOp( lastop );
- PushOp( keynum );
- } else { /* execute lastop on lastnum and dnum, push
- result and current op on stack */
- acc = PopNum();
- switch ( lastop ) { /* perform the operation */
- case kADD: acc += dnum; break;
- case kSUB: acc -= dnum; break;
- case kMUL: acc *= dnum; break;
- case kDIV: acc /= dnum; break;
- case kPOW: acc = pow(acc,dnum); break;
- }
- PushNum( acc );
- PushOp( keynum );
- sprintf( tmpStr,"%.8g", acc);
- DrawDisplay();
- dnum=acc;
- }
- }
- else { /* op stack is empty, push op and num */
- PushOp( keynum );
- PushNum( dnum );
- }
- }
-
-
-
- static void
- PushOp( int op )
- {
- if ( opsp == STACKMAX ) {
- textReg.setValue( "stack error" );
- entered=3;
- }
- else opstack[opsp++]=op;
- }
-
-
-
- static
- int PopOp()
- {
- if ( opsp == 0 ) {
- textReg.setValue( "stack error" );
- entered=3;
- return( kNOP );
- } else
- return( opstack[--opsp] );
- }
-
-
- static void
- PushNum(double num)
- {
- if ( rpn ) {
- numstack[2] = numstack[1];
- numstack[1] = numstack[0];
- numstack[0] = num;
- return;
- }
- if ( numsp == STACKMAX ) {
- textReg.setValue( "stack error" );
- entered=3;
- } else
- numstack[numsp++]=num;
- }
-
-
-
- static
- double PopNum()
- {
- if ( rpn ) {
- double tmp = numstack[0];
- numstack[0] = numstack[1];
- numstack[1] = numstack[2];
- return(tmp);
- }
- if ( numsp == 0 ) {
- textReg.setValue( "stack error" );
- entered=3;
- return 0.0;
- } else
- return( numstack[--numsp] );
- }
-
-
-
- static
- int isopempty()
- {
- return( opsp ? 0 : 1 );
- }
-
-
- static
- int priority(int op)
- {
- switch ( op ) {
- case kPOW: return(2);
- case kMUL:
- case kDIV: return(1);
- case kADD:
- case kSUB: return(0);
- }
- return 0;
- }
-
-
- void parse_double (char *src, char *fmt, double *dp)
- {
- int olderrno = errno;
-
- (void) sscanf (src, fmt, dp);
- errno = olderrno;
- return;
- }
-
-
- static void
- eef()
- {
- flagINV=0;
- if ( clrdisp ) {
- if ( rpn && lift_enabled )
- PushNum( dnum );
- // strcpy(dispstr, rpn ? "1" : "0");
- textReg.setValue( "1" );
- }
- if ( !exponent ) {
- // strcat( dispstr, "E+" );
- textReg.addChar( 'E' );
- textReg.addChar( '+' );
- DrawDisplay();
- exponent = textReg.getLength() - 1;
- // exponent=strlen(dispstr)-1; /* where the '-' goes */
- }
- clrdisp=0;
- entered=1;
- }
-
-
- static void
- ResetCalc()
- {
- flagM = flagINV = flagPAREN = 0; drgmode = DEG;
- // setflag(XCalc_MEMORY, False);
- // setflag(XCalc_INVERSE, False);
- // setflag(XCalc_PAREN, False);
- // setflag(XCalc_RADIAN, False);
- // setflag(XCalc_GRADAM, False);
- // setflag(XCalc_DEGREE, True);
- textReg.setValue("0");
- DrawDisplay();
- ClearStacks();
- drg2rad = PI/180.0;
- rad2drg = 180.0/PI;
- }
-
-
- static void
- offf()
- {
- /* full reset */
- int i;
- ResetCalc();
- entered = clrdisp = 1;
- lift_enabled = 0;
- dnum = mem[0] = 0.0;
- if (rpn)
- for (i = 1 ; i < XCALC_MEMORY; i++)
- mem[i] = 0.0;
- exponent = Dpoint = 0;
- DrawDisplay();
- }
-
-
- static void
- clearf()
- {
- flagINV = 0;
- if (CLR && !rpn) { /* clear all */
- ClearStacks();
- flagPAREN = 0;
- }
- CLR++;
- exponent = Dpoint = 0;
- clrdisp = 1;
- entered = 1;
- textReg.setValue( "0" );
- DrawDisplay();
- }
-
-
- static void
- bkspf()
- {
-
- lift_enabled = 0;
-
- if (! flagINV) {
- if (entered!=1 || clrdisp)
- return;
- if ( textReg.getLength() > 0 )
- textReg.removeTail();
- if ( textReg.getLength() == 0 ) {
- textReg.setValue( "0" );
- clrdisp++;
- }
- }
- else
- {
- textReg.setValue( "0" );
- dnum = 0.0;
- clrdisp++;
- flagINV = 0;
- }
- DrawDisplay();
- }
-
-
- static void
- Quit()
- {
- XtDestroyApplicationContext( appContext );
- exit( 0 );
- }
-
-
-
- static void
- ClearStacks()
- {
- if ( rpn )
- numstack[0] = numstack[1] = numstack[2] = 0.;
- opsp=numsp=0;
- }
-
-
-
- static
- int pre_op( int keynum)
- {
- if ( keynum == -1 )
- return(0);
-
- errno = 0; /* for non-IEEE machines */
-
- if ( ( entered == 3) && !( keynum == kCLR || keynum == kOFF )) {
- if (rpn) {
- clrdisp++;
- } else {
- // ringbell();
- return( 1 ); /* the intent was probably not to do the operation */
- }
- }
-
- if (keynum != kCLR)
- CLR = 0;
- return(0);
- }
-
-
- static void
- rparf()
- {
- double PopNum();
-
- flagINV=0;
- if (!entered)
- return;
-
- if (!flagPAREN)
- return;
-
- clrdisp++;
- Dpoint=exponent=0;
-
- char *tmpStr = textReg.getValue();
- if (entered==1)
- parse_double( tmpStr, "%lf", &dnum );
- entered=2;
-
- PushNum(dnum);
- while ( !isopempty() && ( lastop = PopOp()) != kLPAR ) {
- /* do all pending ops, back to left paren */
- dnum=PopNum();
- acc=PopNum();
- switch ( lastop ) {
- case kADD: acc += dnum;
- break;
- case kSUB: acc -= dnum;
- break;
- case kMUL: acc *= dnum;
- break;
- case kDIV: acc /= dnum;
- break;
- case kPOW: acc = pow( acc, dnum );
- break;
- }
- dnum=acc;
- PushNum( dnum );
- }
- (void) PopNum();
- flagPAREN--;
- entered=2;
- sprintf( tmpStr ,"%.8g", dnum );
- textReg.setValue( tmpStr );
- DrawDisplay();
- }
-
-
- static void
- lparf()
- {
- flagINV=0;
- PushOp( kLPAR );
- flagPAREN++;
- DrawDisplay();
- }
-
-
- static void
- entrf()
- {
- flagINV=0;
- if ( !entered )
- return;
-
- clrdisp=CLR=1;
- Dpoint=exponent=0;
-
- char *tmpStr = textReg.getValue();
- if (entered==1)
- parse_double( tmpStr, "%lf", &dnum );
- entered=2;
- memop = kENTR;
- PushNum( dnum );
- lift_enabled = 0;
- }
-
-
-
- static void
- equf()
- {
- flagINV=0;
- if (!entered)
- return;
-
- clrdisp = CLR =1;
- Dpoint = exponent =0;
-
- char *tmpStr = textReg.getValue();
- if ( entered == 1 )
- parse_double( tmpStr,"%lf", &dnum );
-
- entered = 2;
-
- PushNum( dnum );
-
- while ( !isopempty() ) { /* do all pending ops */
- dnum = PopNum();
- acc = PopNum();
- lastop = PopOp();
- switch ( lastop ) {
- case kADD: acc += dnum;
- break;
- case kSUB: acc -= dnum;
- break;
- case kMUL: acc *= dnum;
- break;
- case kDIV: acc /= dnum;
- break;
- case kPOW: acc = pow( acc, dnum );
- break;
- case kLPAR: flagPAREN--;
- PushNum( acc );
- break;
- }
- dnum = acc;
- PushNum( dnum );
- }
-
- sprintf( tmpStr,"%.8g", dnum );
- textReg.setValue( tmpStr );
- DrawDisplay();
- viewer->render();
- }
-
-
- static void
- drgf()
- {
- char *tmpStr;
- if (flagINV) {
- tmpStr = textReg.getValue();
- if (entered==1)
- parse_double(tmpStr,"%lf",&dnum);
- switch (drgmode) {
- case DEG: dnum=dnum*PI/180.0; break;
- case RAD: dnum=dnum*200.0/PI; break;
- case GRAD: dnum=dnum*90.0/100.0; break;
- }
- entered=2;
- clrdisp=1;
- flagINV=0;
- sprintf( tmpStr,"%.8g",dnum);
- textReg.setValue( tmpStr );
- }
-
- flagINV=0;
- drgmode = (drgmode + 1) % 3;
- switch (drgmode) {
- case DEG: drg2rad=PI / 180.0;
- rad2drg=180.0 / PI;
- break;
- case RAD: drg2rad=1.0;
- rad2drg=1.0;
- break;
- case GRAD: drg2rad=PI / 200.0;
- rad2drg=200.0 / PI;
- break;
- }
- DrawDisplay();
- }
-
-
- static void
- decf()
- {
- flagINV=0;
- if (clrdisp) {
- if (rpn)
- PushNum(dnum);
- textReg.setValue( "0" );
- // strcpy(dispstr,"0");
- }
- if (!Dpoint) {
- textReg.addChar( '.' );
- // strcat(dispstr,".");
- DrawDisplay();
- Dpoint++;
- }
- clrdisp=0;
- entered=1;
- }
-
-
-
- static void
- negf()
- {
- flagINV=0;
- if ( exponent ) { /* neg the exponent */
- if ( textReg.getChar( exponent ) == '-' )
- textReg.replaceChar( exponent, '+');
- else
- textReg.replaceChar( exponent, '+');
- DrawDisplay();
- return;
- }
-
- if ( strcmp("0", textReg.getValue()) == 0 )
- return; /* don't neg a zero */
-
- if ( textReg.getChar( 0 ) == '-' ) /* already neg-ed */
- textReg.removeHead();
- else /* not neg-ed. add a '-' */
- textReg.addHead( '-' );
-
-
- if ( entered == 2 )
- dnum = -1.0 * dnum;
- DrawDisplay();
- }
-
-
-
- static void
- invf()
- {
- flagINV = ~flagINV;
- DrawDisplay();
- }
-
-
- static void
- add( int )
- {
- XCALC_PRE_OP(kADD);
- rpn ? twof(kADD) : twoop(kADD);
- post_op();
- }
-
-
- static void
- subtract( int )
- {
- XCALC_PRE_OP(kSUB);
- rpn ? twof(kSUB) : twoop(kSUB);
- post_op();
- }
-
-
- void divide( int )
- {
- XCALC_PRE_OP(kDIV);
- rpn ? twof(kDIV) : twoop(kDIV);
- post_op();
- }
-
-
- void sum( int )
- {
- XCALC_PRE_OP(kSUM);
- rpn ? memf(kSUM) : oneop(kSUM);
- post_op();
- }
-
-
- void multiply( int )
- {
- XCALC_PRE_OP(kMUL);
- rpn ? twof(kMUL) : twoop(kMUL);
- post_op();
- }
-
-
- void negate( int )
- {
- XCALC_PRE_OP(kNEG);
- negf();
- post_op();
- }
-
-
- void rightParen( int )
- {
- XCALC_PRE_OP(kRPAR);
- rparf();
- post_op();
- }
-
-
- void leftParen( int )
- {
- XCALC_PRE_OP(kLPAR);
- lparf();
- post_op();
- }
-
-
- void equal( int )
- {
- XCALC_PRE_OP(kEQU);
- equf();
- post_op();
- }
-
-
- void enter( int )
- {
- XCALC_PRE_OP(kENTR);
- entrf();
- post_op();
- }
-
-
- void clearit( int )
- {
- XCALC_PRE_OP(kCLR);
- clearf();
- post_op();
- }
-
-
- static
- void decimal( int )
- {
- XCALC_PRE_OP(kDEC);
- decf();
- post_op();
- }
-
-
- void degree(int)
- {
- XCALC_PRE_OP(kDRG);
- drgf();
- post_op();
- }
-
-
- void reciprocal( int )
- {
- XCALC_PRE_OP(kRECIP);
- oneop(kRECIP);
- post_op();
- }
-
-
- void squareRoot( int )
- {
- XCALC_PRE_OP(kSQRT);
- oneop(kSQRT);
- post_op();
- }
-
-
- void power( int )
- {
- XCALC_PRE_OP(kPOW);
- rpn ? twof(kPOW) : twoop(kPOW);
- post_op();
- }
-
-
- void back( int )
- {
- XCALC_PRE_OP(kBKSP);
- bkspf();
- post_op();
- }
-
-
- void cosine( int )
- {
- XCALC_PRE_OP(kCOS);
- oneop(kCOS);
- post_op();
- }
-
-
- void e( int )
- {
- XCALC_PRE_OP(kE);
- oneop(kE);
- post_op();
- }
-
-
- void epower( int )
- {
- XCALC_PRE_OP(kEXP);
- oneop(kEXP);
- post_op();
- }
-
-
-
- void factorial( int )
- {
- XCALC_PRE_OP(kFACT);
- oneop(kFACT);
- post_op();
- }
-
-
- void inverse( int )
- {
- XCALC_PRE_OP(kINV);
- invf();
- post_op();
- }
-
-
-
- void naturalLog( int )
- {
- XCALC_PRE_OP(kLN);
- oneop(kLN);
- post_op();
- }
-
-
- void pi( int )
- {
- XCALC_PRE_OP(kPI);
- oneop(kPI);
- post_op();
- }
-
-
-
- void sine( int )
- {
- XCALC_PRE_OP(kSIN);
- oneop(kSIN);
- post_op();
- }
-
-
- void square( int )
- {
- XCALC_PRE_OP(kSQR);
- oneop(kSQR);
- post_op();
- }
-
-
- void tangent( int )
- {
- XCALC_PRE_OP(kTAN);
- oneop(kTAN);
- post_op();
- }
-
-
- void logarithm( int )
- {
- XCALC_PRE_OP(kLOG);
- oneop(kLOG);
- post_op();
- }
-
-
- void scientific( int )
- {
- XCALC_PRE_OP(kEE);
- eef();
- post_op();
- }
-
-
- static void
- quit( int )
- {
- Quit();
- }
-
-
- void off( int )
- {
- XCALC_PRE_OP(kOFF);
- offf();
- post_op();
- }
-
-